
#include "ldCommInc.h"
#include "ench265.h"
#include "mpp_common.h"
#include "ldUtils.h"

static RK_S32 aq_thd_smart[16] = {
    1,  3,  3,  3,  3,  3,  5,  5,
    8,  8,  8, 15, 15, 20, 25, 28
};

static RK_S32 aq_step_smart[16] = {
    -8, -7, -6, -5, -4, -3, -2, -1,
    0,  1,  2,  3,  4,  6,  8, 10
};

static RK_S32 aq_thd[16] = {
    0,  0,  0,  0,
    3,  3,  5,  5,
    8,  8,  8,  15,
    15, 20, 25, 25
};

static RK_S32 aq_step_i_ipc[16] = {
    -8, -7, -6, -5,
    -4, -3, -2, -1,
    0,  1,  2,  3,
    5,  7,  7,  8,
};

static RK_S32 aq_step_p_ipc[16] = {
    -8, -7, -6, -5,
    -4, -2, -1, -1,
    0,  2,  3,  4,
    6,  8,  9,  10,
};

int  encH265Init(stEncCtx*  pstEncH265,int nChannel,
                 int nWidth,int nHeight,
                 MppFrameFormat  src_fmt,
                 MppCodingType   code_type,
                 int   in_fps,
                 int   in_gop,
                 int   in_bw,
                 bool  isRtsp)
{
    int ret = LD_RES_OK;
    if(pstEncH265 == NULL)
        return  LD_RES_FAILURE;


    pstEncH265->nChn = nChannel;


    log_i("h26x encoder %dx%d %dfps %d kbps",nWidth,nHeight,in_fps,in_bw);



    pstEncH265->cfg_frame_width = nWidth;
    pstEncH265->cfg_frame_height = nHeight;
    pstEncH265->cfg_hor_stride = MPP_ALIGN(pstEncH265->cfg_frame_width, 16);    // for YUV420P it has tobe devided to 16
    pstEncH265->cfg_ver_stride = MPP_ALIGN(pstEncH265->cfg_frame_height, 16);    // for YUV420P it has tobe devided to 16
    pstEncH265->cfg_foramt = src_fmt;    // format of input frame YUV420P MppFrameFormat inside mpp_frame.h

    pstEncH265->cfg_type = code_type ;

    if(isRtsp)
    {
        pstEncH265->cfg_bps     =   8000000;
        pstEncH265->cfg_bps_min =   6000000;
        pstEncH265->cfg_bps_max =  12000000;

    }
    else
    {
        pstEncH265->cfg_bps     =  in_bw;
        pstEncH265->cfg_bps_min =  in_bw;
        pstEncH265->cfg_bps_max =  in_bw;
    }


    pstEncH265->cfg_rc_mode = MPP_ENC_RC_MODE_CBR;    //0:vbr 1:cbr 2:avbr 3:cvbr 4:fixqp;
    pstEncH265->cfg_frame_num = 0;    //max encoding frame number


    pstEncH265->cfg_fps_in_den = 1;
    pstEncH265->cfg_fps_in_num = in_fps;    // input fps

    pstEncH265->cfg_fps_out_den = 1;
    pstEncH265->cfg_fps_out_num = in_fps;
    pstEncH265->timeout = MPP_POLL_BLOCK;

    // update resource parameter
    switch (pstEncH265->cfg_foramt & MPP_FRAME_FMT_MASK)
    {
        case MPP_FMT_YUV420SP:
        case MPP_FMT_YUV420P:
            {
                pstEncH265->cfg_frame_size = MPP_ALIGN(pstEncH265->cfg_hor_stride, 64)*
                                       MPP_ALIGN(pstEncH265->cfg_ver_stride, 64) *3 / 2;
            }
            break;

       case MPP_FMT_YUV400:
            {
                pstEncH265->cfg_frame_size = MPP_ALIGN(pstEncH265->cfg_hor_stride, 64)*
                               MPP_ALIGN(pstEncH265->cfg_ver_stride, 64);
            }
            break;
       case MPP_FMT_YUV422_YUYV :
       case MPP_FMT_YUV422_YVYU :
       case MPP_FMT_YUV422_UYVY :
       case MPP_FMT_YUV422_VYUY :
       case MPP_FMT_YUV422P :
       case MPP_FMT_YUV422SP : {
                pstEncH265->cfg_frame_size = MPP_ALIGN(pstEncH265->cfg_hor_stride, 64) * MPP_ALIGN(pstEncH265->cfg_ver_stride, 64) * 2;
            } break;
       case MPP_FMT_RGB444 :
       case MPP_FMT_BGR444 :
       case MPP_FMT_RGB555 :
       case MPP_FMT_BGR555 :
       case MPP_FMT_RGB565 :
       case MPP_FMT_BGR565 :
       case MPP_FMT_RGB888 :
       case MPP_FMT_BGR888 :
       case MPP_FMT_RGB101010 :
       case MPP_FMT_BGR101010 :
       case MPP_FMT_ARGB8888 :
       case MPP_FMT_ABGR8888 :
       case MPP_FMT_BGRA8888 :
       case MPP_FMT_RGBA8888 :
       {
            pstEncH265->cfg_hor_stride *= 3;
           pstEncH265->cfg_frame_size = MPP_ALIGN(pstEncH265->cfg_hor_stride, 64) * MPP_ALIGN(pstEncH265->cfg_ver_stride, 64);
       } break;

       default: {
           pstEncH265->cfg_frame_size = MPP_ALIGN(pstEncH265->cfg_hor_stride, 64) * MPP_ALIGN(pstEncH265->cfg_ver_stride, 64) * 4;
       } break;
    }

    if(pstEncH265->cfg_frame_size == 0)
    {
        memset(pstEncH265,0,sizeof(stEncCtx));
        log_i("ench265 error, please check");
        return  LD_RES_FAILURE;
    }



    if (MPP_FRAME_FMT_IS_FBC(pstEncH265->cfg_foramt))
        pstEncH265->cfg_header_size = MPP_ALIGN(MPP_ALIGN(pstEncH265->cfg_frame_width, 16)*
                                  MPP_ALIGN(pstEncH265->cfg_frame_height, 16) / 16, SZ_4K);
    else
        pstEncH265->cfg_header_size = 0;

    ret = mpp_buffer_group_get_internal(&pstEncH265->buf_grp, MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_CACHABLE);
    if (ret)
    {
        log_i("failed to get mpp buffer group ret %d\n", ret);
    }


#ifndef LINUX_X86_64

  //ret = mpp_buffer_get(NULL, &pstEncH265->frm_buf, pstEncH265->cfg_frame_size + pstEncH265->cfg_header_size);

    ret = mpp_buffer_get(pstEncH265->buf_grp, &pstEncH265->frm_buf,
                         pstEncH265->cfg_frame_size + pstEncH265->cfg_header_size);
    if (ret)
    {
        log_i("failed to get buffer for input frame ret %d\n", ret);
    }


    ret = mpp_buffer_get(pstEncH265->buf_grp, &pstEncH265->pkt_buf, pstEncH265->cfg_frame_size);
    if (ret)
    {
        log_i("failed to get buffer for output packet ret %d\n", ret);
    }
#endif
    ret = mpp_create(&pstEncH265->ctx, &pstEncH265->mpi);
    if (ret)
    {
        log_i("mpp_create failed ret %d\n", ret);
    }


    ret = pstEncH265->mpi->control(pstEncH265->ctx, MPP_SET_OUTPUT_TIMEOUT,
                                   &pstEncH265->timeout);
    if (MPP_OK != ret)
    {
        log_i("mpi control set output timeout %d ret %d\n", pstEncH265->timeout, ret);
    }

    ret = mpp_init(pstEncH265->ctx, MPP_CTX_ENC, pstEncH265->cfg_type);
    if (ret)
    {
        log_i("mpp_init failed ret %d\n", ret);
    }

    ret = mpp_enc_cfg_init(&pstEncH265->cfg);
    if (ret)
    {
        log_i("mpp_enc_cfg_init failed ret %d\n", ret);
    }

    //configuring the ctx

    pstEncH265->pYUVBuff = new char[FRAME_MAX_LEN];
    pstEncH265->pH265Buff = new char[FRAME_MAX_LEN];


     //low delay
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "base:low_delay", 1);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "prep:width", pstEncH265->cfg_frame_width);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "prep:height", pstEncH265->cfg_frame_height);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "prep:hor_stride", pstEncH265->cfg_hor_stride);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "prep:ver_stride", pstEncH265->cfg_ver_stride);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "prep:format", pstEncH265->cfg_foramt);

    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:mode", pstEncH265->cfg_rc_mode);

    ret = mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:bps", 2000000);





    /*fix input / output frame rate */
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:fps_in_flex", pstEncH265->cfg_fps_in_flex0);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:fps_in_num", pstEncH265->cfg_fps_in_num);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:fps_in_denorm", pstEncH265->cfg_fps_in_den);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:fps_out_flex", pstEncH265->cfg_fps_out_flex0);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:fps_out_num", pstEncH265->cfg_fps_out_num);
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:fps_out_denorm", pstEncH265->cfg_fps_out_den);

    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:gop", 5);

    /*drop frame or not when bitrate overflow */
    mpp_enc_cfg_set_u32(pstEncH265->cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
    mpp_enc_cfg_set_u32(pstEncH265->cfg, "rc:drop_thd", 20); /*20% of max bps */
    mpp_enc_cfg_set_u32(pstEncH265->cfg, "rc:drop_gap", 1); /*Do not continuous drop frame */

    /*setup bitrate for different rc_mode */
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:bps_target", pstEncH265->cfg_bps);
    switch (pstEncH265->cfg_rc_mode)
    {
        case MPP_ENC_RC_MODE_FIXQP:
            {     /*do not setup bitrate on FIXQP mode */
            }
            break;
        case MPP_ENC_RC_MODE_CBR:
            {     /*CBR mode has narrow bound */
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:bps_max",
                                    pstEncH265->cfg_bps_max ? pstEncH265->cfg_bps_max :
                                     pstEncH265->cfg_bps *17 / 16);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:bps_min",
                                    pstEncH265->cfg_bps_min ? pstEncH265->cfg_bps_min :
                                     pstEncH265->cfg_bps *15 / 16);
            }
            break;
        case MPP_ENC_RC_MODE_VBR:
        case MPP_ENC_RC_MODE_AVBR:
            {     /*VBR mode has wide bound */
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:bps_max",
                                    pstEncH265->cfg_bps_max ? pstEncH265->cfg_bps_max :
                                                   pstEncH265->cfg_bps *17 / 16);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:bps_min",
                                    pstEncH265->cfg_bps_min ? pstEncH265->cfg_bps_min :
                                                   pstEncH265->cfg_bps *1 / 16);
            }
            break;
        default:
            {     /*default use CBR mode */
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:bps_max", pstEncH265->cfg_bps_max ?
                                        pstEncH265->cfg_bps_max : pstEncH265->cfg_bps *17 / 16);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:bps_min", pstEncH265->cfg_bps_min ?
                                        pstEncH265->cfg_bps_min : pstEncH265->cfg_bps *15 / 16);
            }
            break;
    }

    /*setup qp for different codec and rc_mode */
    switch (pstEncH265->cfg_type)
    {
        case MPP_VIDEO_CodingAVC:
        case MPP_VIDEO_CodingHEVC:
            {
                switch (pstEncH265->cfg_rc_mode)
                {
                    case MPP_ENC_RC_MODE_FIXQP:
                        {
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_init", 20);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_max", 20);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_min", 20);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_max_i", 20);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_min_i", 20);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_ip", 2);
                        }
                        break;
                    case MPP_ENC_RC_MODE_CBR:
                    case MPP_ENC_RC_MODE_VBR:
                    case MPP_ENC_RC_MODE_AVBR:
                        {
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_init", 26);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_max", 51);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_min", 10);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_max_i", 51);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_min_i", 10);
                            mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_ip", 2);
                        }
                        break;
                case  MPP_ENC_RC_MODE_SMTRC:
                        {
                            mpp_enc_cfg_set_st(pstEncH265->cfg, "hw:aq_thrd_i", aq_thd_smart);
                            mpp_enc_cfg_set_st(pstEncH265->cfg, "hw:aq_thrd_p", aq_thd_smart);
                            mpp_enc_cfg_set_st(pstEncH265->cfg, "hw:aq_step_i", aq_step_smart);
                            mpp_enc_cfg_set_st(pstEncH265->cfg, "hw:aq_step_p", aq_step_smart);
                        }
                        break;
                    default:
                        {
                            log_i("unsupport encoder rc mode %d\n", pstEncH265->cfg_rc_mode);
                        }
                        break;
                }
            }
            break;
        case MPP_VIDEO_CodingVP8:
            {     /*vp8 only setup base qp range */
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_init", 40);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_max", 127);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_min", 0);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_max_i", 127);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_min_i", 0);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "rc:qp_ip", 6);
            }
            break;
        case MPP_VIDEO_CodingMJPEG:
            {     /*jpeg use special codec config to control qtable */
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "jpeg:q_factor", 80);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "jpeg:qf_max", 99);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "jpeg:qf_min", 1);
            }
            break;
        default: {}
            break;
    }

    /*setup codec  */
    mpp_enc_cfg_set_s32(pstEncH265->cfg, "codec:type", pstEncH265->cfg_type);
    switch (pstEncH265->cfg_type)
    {
        case MPP_VIDEO_CodingAVC:
            {     /*
                 *H.264 profile_idc parameter
                 *66  - Baseline profile
                 *77  - Main profile
                 *100 - High profile
                 */
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "h264:profile", 100);
                /*
                 *H.264 level_idc parameter
                 *10 / 11 / 12 / 13    - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
                 *20 / 21 / 22         - cif@30fps / half-D1@@25fps / D1@12.5fps
                 *30 / 31 / 32         - D1@25fps / 720p@30fps / 720p@60fps
                 *40 / 41 / 42         - 1080p@30fps / 1080p@30fps / 1080p@60fps
                 *50 / 51 / 52         - 4K@30fps
                 */
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "h264:level", 41);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "h264:cabac_en", 1);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "h264:cabac_idc", 0);
                mpp_enc_cfg_set_s32(pstEncH265->cfg, "h264:trans8x8", 0);
            }
            break;
        case MPP_VIDEO_CodingHEVC:
            break;
        case MPP_VIDEO_CodingMJPEG:
        case MPP_VIDEO_CodingVP8: {}
            break;
        default:
            {
                log_i("unsupport encoder coding type %d\n", pstEncH265->cfg_type);
            }
            break;
    }

    RK_U32 cfg_split_mode = 0;
    RK_U32 cfg_split_arg = 0;

    mpp_env_get_u32("split_mode", &cfg_split_mode, MPP_ENC_SPLIT_NONE);
    mpp_env_get_u32("split_arg", &cfg_split_arg, 0);

    ret = pstEncH265->mpi->control(pstEncH265->ctx, MPP_ENC_SET_CFG, pstEncH265->cfg);
    if (ret)
    {
        log_i("mpi control enc set cfg failed ret %d\n", ret);
    }


    ret = pstEncH265->mpi->control(pstEncH265->ctx, MPP_ENC_SET_CFG, pstEncH265->cfg);
    if (ret)
    {
        log_i("mpi control enc set cfg failed ret %d\n", ret);
    }


    MppEncSeiMode cfg_sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME;
    ret = pstEncH265->mpi->control(pstEncH265->ctx, MPP_ENC_SET_SEI_CFG, &cfg_sei_mode);
    if (ret)
    {
        log_i("mpi control enc set sei cfg failed ret %d\n", ret);
    }

    if (pstEncH265->cfg_type == MPP_VIDEO_CodingAVC || pstEncH265->cfg_type == MPP_VIDEO_CodingHEVC)
    {
        MppEncHeaderMode cfg_header_mode = MPP_ENC_HEADER_MODE_EACH_IDR;
        ret = pstEncH265->mpi->control(pstEncH265->ctx, MPP_ENC_SET_HEADER_MODE, &cfg_header_mode);
        if (ret)
        {
            log_i("mpi control enc set header mode failed ret %d\n", ret);
        }
    }

    RK_U32 gop_mode = pstEncH265->cfg_gop_mode;

    mpp_env_get_u32("gop_mode", &gop_mode, gop_mode);
    if (gop_mode)
    {
        MppEncRefCfg ref;

        mpp_enc_ref_cfg_init(&ref);

        if (pstEncH265->cfg_gop_mode < 4)
            mpi_enc_gen_ref_cfg(ref, gop_mode);
        else
            mpi_enc_gen_smart_gop_ref_cfg(ref, pstEncH265->cfg_gop_len, pstEncH265->cfg_vi_len);

        ret = pstEncH265->mpi->control(pstEncH265->ctx, MPP_ENC_SET_REF_CFG, ref);
        if (ret)
        {
            log_i("mpi control enc set ref cfg failed ret %d\n", ret);
        }
        mpp_enc_ref_cfg_deinit(&ref);
    }

    RK_U32 cfg_osd_enable, cfg_osd_mode, cfg_roi_enable, cfg_user_data_enable;
    /*setup test mode by env */
    mpp_env_get_u32("osd_enable", &cfg_osd_enable, 0);
    mpp_env_get_u32("osd_mode", &cfg_osd_mode, MPP_ENC_OSD_PLT_TYPE_DEFAULT);
    mpp_env_get_u32("roi_enable", &cfg_roi_enable, 0);
    mpp_env_get_u32("user_data_enable", &cfg_user_data_enable, 0);


    return LD_RES_OK;
}


void encH265GetSpsPPS(stEncCtx*  pstEncH265)
{
   int ret = 0;
   char*  pNPackBuff = NULL;
   if (pstEncH265->cfg_type == MPP_VIDEO_CodingAVC ||
       pstEncH265->cfg_type == MPP_VIDEO_CodingHEVC)
   {
       MppPacket packet = NULL;

       /*
             *Can use packet with normal malloc buffer as input not pkt_buf.
             *Please refer to vpu_api_legacy.cpp for normal buffer case.
             *Using pkt_buf buffer here is just for simplifing demo.
       */

      // mpp_packet_init_with_buffer(&packet, pstEncH265->pkt_buf);
       mpp_packet_init(&packet, pstEncH265->pH265Buff, FRAME_MAX_LEN);

        /*NOTE: It is important to clear output packet length!! */
       mpp_packet_set_length(packet, 0);

       ret = pstEncH265->mpi->control(pstEncH265->ctx, MPP_ENC_GET_HDR_SYNC, packet);
       if (ret)
       {
           log_i("mpi control enc get extra info failed\n");
       }
       else
       {
           /*get and write sps/pps for H.264 */
           void *ptr = mpp_packet_get_pos(packet);
           size_t len = mpp_packet_get_length(packet);
           //if (p->fp_output)
           memcpy((unsigned char*)pstEncH265->ucSpsPpsBuf,(unsigned char*)ptr,len);
           pstEncH265->nSpsPpsLen = len;
       }
       mpp_packet_deinit(&packet);
   }
}



int  encH265Frame(stEncCtx*  pstEncH265,uint8_t* pYUVSrc,uint8_t*  pH265Pack)
{
    int ret = 0;
    MppPacket packet = NULL;
    MppMeta meta = NULL;
    uint32_t eoi = 1;
    //int   packLen = 0;
    int   nWritePos = 0;
    MppFrame frame = NULL;

    if(pstEncH265->cfg_frame_size == 0 || pstEncH265->mpi == nullptr)
    {
        log_i("ench265 error, please check");
        return 0;
    }

    if(pstEncH265->isGetSPS == 0)
    {
        encH265GetSpsPPS(pstEncH265);
        pstEncH265->isGetSPS = 1;
        if(pstEncH265->nSpsPpsLen)
        {
           memcpy(pH265Pack+nWritePos,pstEncH265->ucSpsPpsBuf,pstEncH265->nSpsPpsLen);
           nWritePos += pstEncH265->nSpsPpsLen;
        }
    }


    ret = mpp_frame_init(&frame);
    if (ret)
    {
        log_i("mpp_frame_init failed\n");
    }

    mpp_frame_set_width(frame, pstEncH265->cfg_frame_width);
    mpp_frame_set_height(frame, pstEncH265->cfg_frame_height);
    mpp_frame_set_hor_stride(frame, pstEncH265->cfg_hor_stride);
    mpp_frame_set_ver_stride(frame, 1080);
    mpp_frame_set_fmt(frame, pstEncH265->cfg_foramt);
    mpp_frame_set_eos(frame, 0);




   ret = mpp_buffer_write(pstEncH265->frm_buf, 0, pYUVSrc, pstEncH265->cfg_frame_size);
   if (ret)
   {
        log_e("could not write data on frame\n", pstEncH265->nChn);
        return 0;
   }
   mpp_frame_set_buffer(frame, pstEncH265->frm_buf);
   meta = mpp_frame_get_meta(frame);





    mpp_packet_init(&packet, pstEncH265->pH265Buff, FRAME_MAX_LEN);
    /*NOTE: It is important to clear output packet length!! */
    mpp_packet_set_length(packet, 0);
    mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet);


    ret = pstEncH265->mpi->encode_put_frame(pstEncH265->ctx, frame);
    if (ret)
    {
        log_e("chn %d encode put frame failed\n", pstEncH265->nChn);
        mpp_frame_deinit(&frame);
        return LD_RES_FAILURE;
    }
    mpp_frame_deinit(&frame);

    do
    {
       ret = pstEncH265->mpi->encode_get_packet(pstEncH265->ctx, &packet);
       if (ret)
        {
            log_e("chn %d encode get packet failed\n", pstEncH265->nChn);
        }

        mpp_assert(packet);
        if (packet)
        {
            // write packet to file here
            void *ptr = mpp_packet_get_pos(packet);
            size_t len = mpp_packet_get_length(packet);
            memcpy((unsigned char*)(pH265Pack + nWritePos),(unsigned char*)ptr,len);
            nWritePos += len;
            //std::cout<<"write packet to file here.len:"<<len<<"\n";
            if (mpp_packet_is_partition(packet))
            {
                eoi = mpp_packet_is_eoi(packet);
            }
        }
        else
        {
            log_i("there is no packet\n");
        }
        mpp_packet_deinit(&packet);
    } while (!eoi);
    return nWritePos;
}

int  encH265Release(stEncCtx*  pstEncH265)
{

    if(pstEncH265 == NULL)
        return LD_RES_FAILURE;

    if (pstEncH265->ctx)
    {
        mpp_destroy(pstEncH265->ctx);
        pstEncH265->ctx = NULL;
    }

    if (pstEncH265->cfg)
    {
        mpp_enc_cfg_deinit(pstEncH265->cfg);
        pstEncH265->cfg = NULL;
    }

    if (pstEncH265->frm_buf)
    {
        mpp_buffer_put(pstEncH265->frm_buf);
        pstEncH265->frm_buf = NULL;
    }

    if (pstEncH265->pkt_buf)
    {
        mpp_buffer_put(pstEncH265->pkt_buf);
        pstEncH265->pkt_buf = NULL;
    }

    if (pstEncH265->buf_grp)
    {
        mpp_buffer_group_put(pstEncH265->buf_grp);
        pstEncH265->buf_grp = NULL;
    }


   return  LD_RES_OK;
}









